package com.gxp.system.service.impl;

import com.gxp.common.constant.AutomationConstants;
import com.gxp.common.core.text.Convert;
import com.gxp.common.exception.ServiceException;
import com.gxp.common.utils.*;
import com.gxp.common.utils.uuid.IdUtils;
import com.gxp.system.domain.*;
import com.gxp.system.domain.dto.ServicesDto;
import com.gxp.system.mapper.*;
import com.gxp.system.service.IZknjRequestService;
import com.gxp.system.service.IZknjServiceService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 请求Service业务层处理
 * 
 * @author zh
 * @date 2024-08-06
 */
@Service
public class ZknjRequestServiceImpl implements IZknjRequestService 
{
    @Autowired
    private ZknjRequestMapper zknjRequestMapper;
    @Autowired
    private ZknjSampleMapper sampleMapper;
    @Autowired
    private ZknjReqSamInfMapper reqSamInfMapper;
    @Autowired
    private IZknjServiceService zknjServiceService;
    @Autowired
    private ZknjMethodMapper methodMapper;
    @Autowired
    private ZknjServiceInstanceMapper zknjServiceInstanceMapper;
    @Autowired
    private ZkPendingExpMapper expMapper;
    @Autowired
    private ZknjProUserMapper proUserMapper;
    @Autowired
    private ZknjProjectMapper projectMapper;
    @Autowired
    private ZknjDocumentMapper documentMapper;


    /**
     * 查询请求
     * @param reqId 请求主键
     * @return 请求
     */
    @Override
    public ZknjRequest selectZknjRequestByReqId(Long reqId)
    {
        ZknjRequest zknjRequest = zknjRequestMapper.selectZknjRequestByReqId(reqId);
        setDocuments(zknjRequest);
        setSamAndSer(zknjRequest);
        return zknjRequest;
    }

    /**
     * 查询请求ID列表（分页）
     * @param zknjRequest
     * @return
     */
    @Override
    public List<Long> selectZknjRequestIdList(ZknjRequest zknjRequest) {
        return zknjRequestMapper.selectZknjRequestIdList(zknjRequest);
    }

    /**
     * 根据ID查询请求列表
     * @param ids
     * @return
     */
    @Override
    public List<ZknjRequest> selectZknjRequestListByIds(List<Long> ids) {
        List<ZknjRequest> requests = zknjRequestMapper.selectZknjRequestListByIds(ids);
        setSamAndSer(requests);
        return requests;
    }

    /**
     * 查询请求列表
     * @param zknjRequest 请求
     * @return 请求
     */
    @Override
    public List<ZknjRequest> selectZknjRequestList(ZknjRequest zknjRequest)
    {
        List<ZknjRequest> requests = zknjRequestMapper.selectZknjRequestList(zknjRequest);
        //增加documents信息
        setDocuments(requests);
        //增加样品和服务信息
        setSamAndSer(requests);
        return requests;
    }

    @Override
    public List<ZknjRequest> selectZknjRequestListForVerify(ZknjRequest zknjRequest) {
        List<ZknjRequest> requests = zknjRequestMapper.selectZknjRequestListForVerify(zknjRequest);
        //增加documents信息
        setDocuments(requests);
        //增加样品和服务信息
        setSamAndSer(requests);
        return requests;
    }

    /**
     * 根据项目ID查询请求列表
     * @return
     */
    @Override
    public List<ZknjRequest> selectZknjRequestListByProIds( ZknjRequest zknjRequest) {
        List<ZknjRequest> requests = zknjRequestMapper.selectZknjRequestList(zknjRequest);
        setSamAndSer(requests);
        return requests;
    }

    /**
     * 根据实验信息ID查询请求
     * @param infId
     * @return
     */
    @Override
    public ZknjRequest selectZknjRequestByInfId(Long infId) {
        ZknjRequest zknjRequest = zknjRequestMapper.selectOneByInfId(infId);
        setSamAndSer(zknjRequest);
        return zknjRequest;
    }

    @Override
    public void updateZknjRequestStatus(ZknjRequest zknjRequest) {
        zknjRequestMapper.updateZknjRequest(zknjRequest);
    }

    /**
     * 设置请求documents信息
     * @param requests
     */
    private void setDocuments(List<ZknjRequest> requests) {
        requests.forEach(request -> {
            ZknjDocument document = new ZknjDocument();
            document.setReqId(request.getReqId());
            List<ZknjDocument> zknjDocuments = documentMapper.selectZknjDocumentList(document);
            if (zknjDocuments != null && !zknjDocuments.isEmpty()) {
                request.setDocuments(zknjDocuments);
            } else {
                request.setDocuments(new ArrayList<>());
            }
        });
    }

    /**
     * 设置请求documents信息
     * @param request
     */
    private void setDocuments(ZknjRequest request) {
        ZknjDocument document = new ZknjDocument();
        document.setReqId(request.getReqId());
        List<ZknjDocument> zknjDocuments = documentMapper.selectZknjDocumentList(document);
        if (zknjDocuments != null && !zknjDocuments.isEmpty()) {
            request.setDocuments(zknjDocuments);
        } else {
            request.setDocuments(new ArrayList<>());
        }
    }

    /**
     * 批量填充
     */
    private void setSamAndSer(List<ZknjRequest> requests) {
        requests.forEach(request -> {
            request.setSamples(sampleMapper.selectZknjSampleByReqId(request.getReqId()));
            request.setServices(zknjServiceInstanceMapper.selectListByReqId(request.getReqId()));
        });
    }

    /**
     * 单个填充
     */
    private void setSamAndSer(ZknjRequest request) {
        List<ZknjSample> samples = sampleMapper.selectZknjSampleByReqId(request.getReqId());
        getserAndMod(samples);
        request.setSamples(samples);
        request.setServices(zknjServiceInstanceMapper.selectListByReqId(request.getReqId()));
    }

    private void getserAndMod(List<ZknjSample> samples) {
        samples.forEach(sample -> {
            List<ZknjServiceInstance> sas = zknjServiceInstanceMapper.selectListBySamId(sample.getSamId());
            List<Long> collect = sas.stream().map(ZknjServiceInstance::getModId).collect(Collectors.toList());
            String modIds = StringUtils.join(collect, ",");
            ServicesDto servicesDto = zknjServiceService.selectZknjServiceAndMethodByModIds(modIds);
            sample.setMethods(servicesDto.getMethods());
            sample.setServices(servicesDto.getServices());
        });
    }

    /**
     * 新增请求
     * 
     * @param zknjRequest 请求
     * @return 结果
     */
    @Override
    public int insertZknjRequest(ZknjRequest zknjRequest)
    {
        zknjRequest.setCreateTime(DateUtils.getNowDate());
        zknjRequest.setReqStatus(Long.valueOf(DictUtils.getDictValue("sys_request_status", "Edit")));
        return zknjRequestMapper.insertZknjRequest(zknjRequest);
    }

    /* 添加sample与method关系表*/
    public void insertReqSamMod(ZknjSample sample, Long reqId, List<Map<String, String>> servicesAudit) {
        String modIds = sample.getModIds();
        String[] split = modIds.split(",");
        if(split.length == 1){
            Long modId = Long.valueOf(modIds.trim());
            insertZknjReqSam(reqId, modId, sample, servicesAudit);
        }else {
            for (String s : split) {
                Long modId = Long.valueOf(s.trim());
                insertZknjReqSam(reqId, modId, sample, servicesAudit);
            }
        }
    }

    /**
     * 添加zknj_information表和req_sam_inf表信息
     */
    private void insertZknjReqSam(Long reqId, Long modId, ZknjSample sample, List<Map<String, String>> servicesAudit) {
        ZknjMethod method = methodMapper.selectZknjMethodByModId(modId);
        ZknjService zknjService = zknjServiceService.selectZknjServiceBySerId(method.getSerId());
        ZknjServiceInstance info = getZknjInfoFromSerAndMod(zknjService, method);
        info.setCreateBy(sample.getCreateBy());
        info.setCreateTime(DateUtils.getNowDate());
        info.setProcess(Long.valueOf(DictUtils.getDictValue("auto_exp_status", "Editable")));
        info.setModId(modId);
        info.setPriority(sample.getPriority());
        zknjServiceInstanceMapper.insertZknjServiceInstance(info);
        //如果services不为空，说明是从服务申请过来的
        if(servicesAudit != null){
            Map<String, String> serviceMap = new HashMap<>();
            serviceMap.put("entityId", info.getInfId().toString());
            serviceMap.put("Sample Name", info.getSerName());
            serviceMap.put("Service Type", info.getSvtypeName());
            serviceMap.put("Experiment", info.getTemplateName());
            serviceMap.put("Experiment Code", info.getExpcode());
            serviceMap.put("Instrument", zknjService.getInstrument().getInstName());
            serviceMap.put("Acquisition Parameters", info.getAcqupara());
            serviceMap.put("Slot", String.valueOf(info.getPriority()));
            serviceMap.put("Solvent", sample.getSolvent());
            servicesAudit.add(serviceMap);
        }
        ZknjReqSamInf zknjReqSam = new ZknjReqSamInf();
        zknjReqSam.setReqId(reqId);
        zknjReqSam.setSamId(sample.getSamId());
        zknjReqSam.setInfId(info.getInfId());
        reqSamInfMapper.insertZknjReqSam(zknjReqSam);
    }

    /**
     * 由Service和选择的method转化成实验信息对象
     */
    private ZknjServiceInstance getZknjInfoFromSerAndMod(ZknjService service, ZknjMethod method) {
        ZknjServiceInstance zknjInfo = new ZknjServiceInstance();
        zknjInfo.setAcqupara(method.getModAcqupara());
        zknjInfo.setExpcode(IdUtils.fastSimpleUUID());
        zknjInfo.setInstId(service.getInstId());
        zknjInfo.setSvtypeName(service.getServiceType().getSvtypeName());
        zknjInfo.setTemplateName(method.getTemplateName());
        zknjInfo.setSerName(service.getSerName());
        zknjInfo.setSerId(service.getSerId());
//        zknjInfo.setPriority();
        return zknjInfo;
    }

    /**
     * 修改请求
     * 
     * @param zknjRequest 请求
     * @return 结果
     */
    @Override
    public int updateZknjRequest(ZknjRequest zknjRequest)
    {
        zknjRequest.setUpdateTime(DateUtils.getNowDate());
//        List<ZknjSample> samplesNew = zknjRequest.getSamples();
//        List<ZknjSample> samplesOld = sampleMapper.selectZknjSampleByReqId(zknjRequest.getReqId());
//        List<Long> samIdsOld = samplesOld.stream().map(ZknjSample::getSamId).collect(Collectors.toList());
//        List<Long> samIdsNew = samplesNew.stream().map(ZknjSample::getSamId).collect(Collectors.toCollection(ArrayList::new));  // 防止出现空指针
//        List<Long> delSamIds = samIdsOld.stream().filter(samId -> !samIdsNew.contains(samId)).collect(Collectors.toList());
//        delSamIds.forEach(samId ->{
//            //Delete Sample
//            sampleMapper.deleteZknjSampleBySamId(samId);
//            //Delete Service
//            zknjServiceInstanceMapper.deleteListBySamId(samId);
//            //Audit
//
//            //Delete Relation
//            reqSamInfMapper.deleteZknjReqSamBySamId(samId);
//        });
//        samplesNew.forEach(sample -> {
//            if(sample.getSamId() == null){
//                //Add sample
//                sample.setCreateBy(ShiroUtils.getLoginName());
//                sample.setCreateTime(DateUtils.getNowDate());
//                sampleMapper.insertZknjSample(sample);
//                insertReqSamMod(sample, zknjRequest.getReqId());
//                //Audit
//
//            }else {
//                //Edit Sample
//                sample.setUpdateBy(ShiroUtils.getLoginName());
//                sample.setUpdateTime(DateUtils.getNowDate());
//                sampleMapper.updateZknjSample(sample);
//                updateReqSamMod(sample, zknjRequest.getReqId());
//            }
//        });
        return zknjRequestMapper.updateZknjRequest(zknjRequest);
    }

    /**
     * 样品服务修改
     */
    public void updateReqSamMod(ZknjSample sample, Long reqId) {
        List<ZknjServiceInstance> zknjServiceInstances = zknjServiceInstanceMapper.selectListBySamId(sample.getSamId());
        List<Long> modIdsOld = zknjServiceInstances.stream().map(ZknjServiceInstance::getModId).collect(Collectors.toList());
        List<Long> modIdsNew = Arrays.stream(sample.getModIds().split(",")).map(Long::valueOf).collect(Collectors.toList());
        //新增服务
        List<Long> addModIds = modIdsNew.stream().filter(id -> !modIdsOld.contains(id)).collect(Collectors.toList());
        //删除服务
        List<Long> delModIds = modIdsOld.stream().filter(id -> !modIdsNew.contains(id)).collect(Collectors.toList());
        if(!addModIds.isEmpty()){
            addModIds.forEach(modId -> insertZknjReqSam(reqId, modId, sample, null));
        }
        if(!delModIds.isEmpty()){
            delModIds.forEach(modId -> deleteSamSer(zknjServiceInstances, modId));
        }
    }

    /**
     * 删除样品中的某个服务
     */
    private void deleteSamSer(List<ZknjServiceInstance> zknjServiceInstances, Long modId) {
        for (ZknjServiceInstance zknjServiceInstance : zknjServiceInstances) {
            if(zknjServiceInstance.getModId().longValue() == modId.longValue()) {
                zknjServiceInstanceMapper.deleteZknjServiceInstanceByInfId(zknjServiceInstance.getInfId());
            }
        }
    }

    /**
     * 批量删除请求
     * @param reqIds 需要删除的请求主键
     * @return 结果
     */
    @Override
    public int deleteZknjRequestByReqIds(String reqIds)
    {
        Long[] longArray = Convert.toLongArray(reqIds);
        for (Long reqId : longArray) {
            ZknjRequest zknjRequest = zknjRequestMapper.selectZknjRequestByReqId(reqId);
            if(
                    zknjRequest.getReqStatus().longValue() == Long.valueOf(DictUtils.getDictValue("sys_request_status", "Edit")).longValue() ||
                    zknjRequest.getReqStatus().longValue() == Long.valueOf(DictUtils.getDictValue("sys_request_status", "Cancelled")).longValue() ||
                    zknjRequest.getReqStatus().longValue() == Long.valueOf(DictUtils.getDictValue("sys_request_status", "error")).longValue()||
                    zknjRequest.getReqStatus().longValue() == Long.valueOf(DictUtils.getDictValue("sys_request_status", "Completed")).longValue()
            ){
                //删除sample
                sampleMapper.deleteZknjSampleByReqId(reqId);
                //删除serviceActive
                zknjServiceInstanceMapper.deleteListByReqId(reqId);
                //删除关系表
                reqSamInfMapper.deleteZknjReqSamByReqId(reqId);
            }else {
                throw  new ServiceException("服务申请正在进行中，无法删除");
            }

        }
        return zknjRequestMapper.deleteZknjRequestByReqIds(Convert.toStrArray(reqIds));
    }

    /**
     * 删除请求信息
     * 
     * @param reqId 请求主键
     * @return 结果
     */
    @Override
    public int deleteZknjRequestByReqId(Long reqId)
    {
        //删除sample
        sampleMapper.deleteZknjSampleByReqId(reqId);
        //删除serviceActive
        zknjServiceInstanceMapper.deleteListByReqId(reqId);
        //删除关系表
        reqSamInfMapper.deleteZknjReqSamByReqId(reqId);
        return zknjRequestMapper.deleteZknjRequestByReqId(reqId);
    }

    /**
     * 取消申请
     */
    @Override
    public int cancelZknjRequestByReqIds(String id) {
        Long reqId = Long.valueOf(id);
        ZknjRequest zknjRequest = new ZknjRequest();
        zknjRequest.setReqId(reqId);
        zknjRequest.setReqStatus(Long.valueOf(DictUtils.getDictValue("sys_request_status", "Cancelled")));
        //TODO: 取消申请的其它操作

        return zknjRequestMapper.updateZknjRequest(zknjRequest);
    }

    /**
     * 取消后重新验证
     * @param id
     * @return
     */
    @Override
    public int reapproveZknjRequestByReqIds(String id) {
        Long reqId = Long.valueOf(id);
        ZknjRequest zknjRequest = new ZknjRequest();
        zknjRequest.setReqId(reqId);
        zknjRequest.setReqStatus(Long.valueOf(DictUtils.getDictValue("sys_request_status", "pending verification")));
        //所有服务状态改为等待验证
        List<ZknjServiceInstance> services = zknjServiceInstanceMapper.selectListByReqId(reqId);
        services.forEach(service -> {
            if(service.getSerStatus().equals(Long.valueOf(DictUtils.getDictValue("sys_service_status", "Cancelled")))){
                ZknjServiceInstance serviceActive = new ZknjServiceInstance();
                serviceActive.setInfId(service.getInfId());
                serviceActive.setSerStatus(Long.valueOf(DictUtils.getDictValue("sys_service_status", "pending verification")));
                zknjServiceInstanceMapper.updateZknjServiceInstance(serviceActive);
            }
        });

        return zknjRequestMapper.updateZknjRequest(zknjRequest);
    }

    /**
     * request 提交
     */
    @Override
    public int submit(ZknjRequest zkRequest) {

        if(sub2AutoExp(zkRequest, IpUtils.getIpAddr(ServletUtils.getRequest()), ShiroUtils.getLoginName())){
            //修改状态
            zkRequest.getServices().forEach(service -> {
                ZknjServiceInstance serviceActive = new ZknjServiceInstance();
                serviceActive.setInfId(service.getInfId());
                serviceActive.setProcess(Long.valueOf(DictUtils.getDictValue("auto_exp_status","Submitted")));
                zknjServiceInstanceMapper.updateZknjServiceInstance(serviceActive);
            });
            ZknjRequest zknjRequest = new ZknjRequest();
            zknjRequest.setReqId(zkRequest.getReqId());
            zknjRequest.setReqStatus(Long.valueOf(DictUtils.getDictValue("sys_request_status","Submit")));
            zknjRequestMapper.updateZknjRequest(zknjRequest);
        }else {
            //提交失败 TODO
            return 0;
        }
        return 1;
    }

    /**
     * 提交到自动化实验待拉取数据库
     * @param request 申请信息
     * @param ip ip地址
     * @param userName 申请人名称
     */
    private boolean sub2AutoExp(ZknjRequest request , String ip, String userName) {
        List<ZknjServiceInstance> services = request.getServices();
        for (ZknjServiceInstance service : services) {
            ZkPendingExp exp = new ZkPendingExp();
            getExpFromService(service, exp);
            exp.setCreateTime(DateUtils.getNowDate());
            exp.setType(AutomationConstants.EXP_TYPE_SUBMIT);
            exp.setExpmode(1);
            exp.setReadCount(0);
            exp.setExpcode(service.getExpcode());
            exp.setIp(ip);
//            exp.setUser("gxp");
            exp.setUser(userName);
//            exp.setRequester();
            int insert = expMapper.insertZkPendingExp(exp);
            //提交失败
            if(insert != 1){
                return false;
            }
        }
        return true;
    }

    /**
     * 转化信息 service -> exp
     */
    private void getExpFromService(ZknjServiceInstance service, ZkPendingExp exp) {
        ZknjSample sample = service.getSample();
        exp.setExpName(sample.getSamName());
        exp.setHostId(service.getInstrument().getHostId());
        exp.setSlot(sample.getSamSlot());
        exp.setSolvent(sample.getSolvent());
        exp.setExperiment(service.getTemplateName());
        exp.setExpparams(service.getAcqupara());
        exp.setServiceId(service.getInfId());

    }

    /**
     * 申请信息修改
     */
    @Override
    public int updateSevAndSam(ZknjSample sample, ZknjServiceInstance serviceActive) {
        ZknjServiceInstance service = zknjServiceInstanceMapper.selectZknjServiceInstanceByInfId(serviceActive.getInfId());
        if (service.getSerId().longValue() != serviceActive.getSerId().longValue()) {
            //服务修改
            ZknjService zknjService = zknjServiceService.selectZknjServiceBySerId(serviceActive.getSerId());
            serviceActive.setSerId(zknjService.getSerId());
            serviceActive.setSvtypeName(zknjService.getServiceType().getSvtypeName());
            serviceActive.setSerName(zknjService.getSerName());
            serviceActive.setInstId(zknjService.getInstId());
        }
        if (service.getModId().longValue() != serviceActive.getModId().longValue()) {
            //方法修改
            ZknjMethod method = methodMapper.selectZknjMethodByModId(serviceActive.getModId());
            serviceActive.setTemplateName(method.getTemplateName());
            serviceActive.setAcqupara(method.getModAcqupara());
            serviceActive.setModId(method.getModId());
        }
        serviceActive.setUpdateBy(ShiroUtils.getLoginName());
        serviceActive.setUpdateTime(DateUtils.getNowDate());
        zknjServiceInstanceMapper.updateZknjServiceInstance(serviceActive);
        return sampleMapper.updateZknjSample(sample);
    }

    /**
     * 从历史数据表中查询数据
     */
    @Override
    public List<ZknjRequest> selectZknjRequestListForHistory(ZknjRequest zknjRequest) {
        List<ZknjRequest> requests = zknjRequestMapper.selectZknjRequestListForHistory(zknjRequest);
        requests.forEach(request -> {
            request.setSamples(sampleMapper.selectZknjSampleByReqIdForHistory(request.getReqId()));
            request.setServices(zknjServiceInstanceMapper.selectListByReqIdForHistory(request.getReqId()));
        });
        return requests;
    }

    /**
     * 更新 request 状态为 pending results
     */
    @Override
    public void updateStatus(List<String> expcodes, Long status) {
        List<Long> reqIds = new ArrayList<>();
        for (String expcode : expcodes) {
            Long reqId = zknjRequestMapper.selectOneByExpcode(expcode).getReqId();
            if(!reqIds.contains(reqId)){
                reqIds.add(reqId);
            }
        }
        reqIds.forEach(reqId -> {
            ZknjRequest request = new ZknjRequest();
            request.setReqId(reqId);
            request.setReqStatus(status);
            zknjRequestMapper.updateZknjRequest(request);
        });
    }

    /**
     * 自动化实验返回拉取成功或者失败，对应修改状态
     */
    @Override
    public void updateStatus(String expcode, Long status) {
        Long reqId = zknjRequestMapper.selectOneByExpcode(expcode).getReqId();
        ZknjRequest zknjRequest = new ZknjRequest();
        zknjRequest.setReqStatus(status);
        zknjRequest.setReqId(reqId);
        zknjRequestMapper.updateZknjRequest(zknjRequest);
    }
}
